﻿using FMStudio.Documents.TemplateDocument.Properties;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.IO;
using FMStudio.Documents.TemplateDocument.Models;

namespace FMStudio.Documents.TemplateDocument.Test
{
    [TestClass]
    public class TemplateDocumentTypeTest
    {
        private string TestPath1 = Path.Combine(Environment.CurrentDirectory, "Template1.fmstemplate");
        private string TestPath2 = Path.Combine(Environment.CurrentDirectory, "Template2.fmstemplate");


        [TestInitialize]
        public void TestCleanup()
        {
            if (File.Exists(TestPath1))
                File.Delete(TestPath1);
            if (File.Exists(TestPath2))
                File.Delete(TestPath2);
        }


        [TestMethod]
        public void DocumentTypeTest()
        {
            TemplateDocumentType documentType = new TemplateDocumentType();
            Assert.AreEqual(Resources.DocumentExtension, documentType.FileExtension);
            Assert.AreEqual(Resources.DocumentDescription, documentType.Description);
        }

        [TestMethod]
        public void NewDocumentTest()
        {
            TemplateDocumentType documentType = new TemplateDocumentType();
            Assert.IsTrue(documentType.CanNew());

            //  Project Template
            TemplateDocument projectDocument = documentType.New(TestPath1);
            documentType.Save(projectDocument);
            Assert.IsTrue(File.Exists(TestPath1));
            Assert.IsNotNull(projectDocument);

            Assert.AreEqual(TemplateType.Project, projectDocument.Type);
            Assert.IsNotNull(projectDocument.TemplateData);
            Assert.AreEqual("Template1", projectDocument.TemplateData.Name);
            Assert.IsFalse(projectDocument.IsModified);
            Assert.IsNotNull(projectDocument.TemplateContent);
            Assert.AreEqual(0, projectDocument.TemplateContent.Items.Count);

            //  Item Template
            TemplateDocument itemDocument = documentType.New(TestPath2, TemplateType.Item);
            documentType.Save(itemDocument);
            Assert.IsTrue(File.Exists(TestPath2));
            Assert.IsNotNull(itemDocument);

            Assert.AreEqual(TemplateType.Item, itemDocument.Type);
            Assert.IsNotNull(itemDocument.TemplateData);
            Assert.AreEqual("Template2", itemDocument.TemplateData.Name);
            Assert.IsFalse(itemDocument.IsModified);
            Assert.IsNotNull(itemDocument.TemplateContent);
            Assert.AreEqual(0, itemDocument.TemplateContent.Items.Count);
        }

        [TestMethod]
        public void SaveAndOpenProjectTemplateDocumentTest()
        {
            TemplateDocumentType documentType = new TemplateDocumentType();
            TemplateDocument document = documentType.New(TestPath1);

            Assert.IsTrue(documentType.CanSave(document));
            documentType.Save(document, TestPath1);
            Assert.IsTrue(File.Exists(TestPath1));

            Assert.IsTrue(documentType.CanOpen());
            TemplateDocument openedDocument = documentType.Open(TestPath1);
            Assert.AreEqual(document.TemplateData.Name, openedDocument.TemplateData.Name);

            //  Template Data
            openedDocument = null;
            document.TemplateData.NumberOfParentCategoriesToRollUp = 1;
            document.TemplateData.SortOrder = 10;

            documentType.Save(document, TestPath1);
            openedDocument = documentType.Open(TestPath1);

            Assert.AreEqual(document.TemplateData.NumberOfParentCategoriesToRollUp, openedDocument.TemplateData.NumberOfParentCategoriesToRollUp);
            Assert.AreEqual(document.TemplateData.SortOrder, openedDocument.TemplateData.SortOrder);

            //  Template Content
            openedDocument = null;
            (document.TemplateContent as ProjectTemplateContent).Name = "SomeProject.fmproj";
            (document.TemplateContent as ProjectTemplateContent).TargetName = "NewProject.fmproj";
            Folder folder = new Folder() { Name = "Folder", TargetFolderName = "NewFolder" };
            folder.Items.Add(new Folder() { Name = "Folder2", TargetFolderName = "NewFolder2" });
            folder.Items.Add(new ProjectItem() { Name = "Item1", TargetFileName = "NewItem1", ReplaceParameters = true });
            document.TemplateContent.Items.Add(folder);
            document.TemplateContent.Items.Add(new ProjectItem() { Name = "Item2", TargetFileName = "NewItem2" });

            documentType.Save(document, TestPath1);
            openedDocument = documentType.Open(TestPath1);

            Assert.AreEqual((document.TemplateContent as ProjectTemplateContent).Name, (openedDocument.TemplateContent as ProjectTemplateContent).Name);
            Assert.AreEqual((document.TemplateContent as ProjectTemplateContent).TargetName, (openedDocument.TemplateContent as ProjectTemplateContent).TargetName);

            Folder openFolder = openedDocument.TemplateContent.Items.First(x=>x is Folder) as Folder;
            Assert.AreEqual(folder.Name, openFolder.Name);
            Assert.AreEqual(folder.TargetFolderName, openFolder.TargetFolderName);
            Assert.AreEqual(folder.Items.Count, openFolder.Items.Count);

            Folder folder2 = folder.Items.First(x => x is Folder) as Folder;
            Folder openfolder2 = openFolder.Items.First(x => x is Folder) as Folder;
            Assert.AreEqual(folder2.Name, openfolder2.Name);
            Assert.AreEqual(folder2.TargetFolderName, openfolder2.TargetFolderName);
            Assert.AreEqual(folder2.Items.Count, openfolder2.Items.Count);

            ProjectItem item1 = folder.Items.First(x => x is ProjectItem) as ProjectItem;
            ProjectItem openItem1 = openFolder.Items.First(x => x is ProjectItem) as ProjectItem;
            Assert.AreEqual(item1.Name, openItem1.Name);
            Assert.AreEqual(item1.TargetFileName, openItem1.TargetFileName);
            Assert.AreEqual(item1.ReplaceParameters, openItem1.ReplaceParameters);

            ProjectItem item2 = document.TemplateContent.Items.First(x => x is ProjectItem) as ProjectItem;
            ProjectItem openItem2 = openedDocument.TemplateContent.Items.First(x => x is ProjectItem) as ProjectItem;
            Assert.AreEqual(item2.Name, openItem2.Name);
            Assert.AreEqual(item2.TargetFileName, openItem2.TargetFileName);
            Assert.AreEqual(item2.ReplaceParameters, openItem2.ReplaceParameters);

            //  Wizard Extension
            openedDocument = null;
            Assert.IsNull(document.WizardExtension);
            document.WizardExtension = new TemplateWizard();
            document.WizardExtension.Assembly = "SomeAssembly";
            document.WizardExtension.FullClassName = "SomeClass";

            documentType.Save(document, TestPath1);
            openedDocument = documentType.Open(TestPath1);

            Assert.IsNotNull(openedDocument.WizardExtension);
            Assert.AreEqual(document.WizardExtension.Assembly, openedDocument.WizardExtension.Assembly);
            Assert.AreEqual(document.WizardExtension.FullClassName, openedDocument.WizardExtension.FullClassName);
        }


        [TestMethod]
        public void SaveAndOpenItemTemplateDocumentTest()
        {
            TemplateDocumentType documentType = new TemplateDocumentType();
            TemplateDocument document = documentType.New(TestPath2, TemplateType.Item);

            Assert.IsTrue(documentType.CanSave(document));
            documentType.Save(document, TestPath2);
            Assert.IsTrue(File.Exists(TestPath2));

            Assert.IsTrue(documentType.CanOpen());
            TemplateDocument openedDocument = documentType.Open(TestPath2);
            Assert.AreEqual(document.TemplateData.Name, openedDocument.TemplateData.Name);

            //  Template Data
            openedDocument = null;
            document.TemplateData.NumberOfParentCategoriesToRollUp = 1;
            document.TemplateData.SortOrder = 10;

            documentType.Save(document, TestPath2);
            openedDocument = documentType.Open(TestPath2);

            Assert.AreEqual(document.TemplateData.NumberOfParentCategoriesToRollUp, openedDocument.TemplateData.NumberOfParentCategoriesToRollUp);
            Assert.AreEqual(document.TemplateData.SortOrder, openedDocument.TemplateData.SortOrder);

            //  Template Content
            openedDocument = null;
            Folder folder = new Folder() { Name = "Folder", TargetFolderName = "NewFolder" };
            folder.Items.Add(new Folder() { Name = "Folder2", TargetFolderName = "NewFolder2" });
            folder.Items.Add(new ProjectItem() { Name = "Item1", TargetFileName = "NewItem1", ReplaceParameters = true });
            document.TemplateContent.Items.Add(folder);
            document.TemplateContent.Items.Add(new ProjectItem() { Name = "Item2", TargetFileName = "NewItem2" });

            documentType.Save(document, TestPath2);
            openedDocument = documentType.Open(TestPath2);

            Folder openFolder = openedDocument.TemplateContent.Items.First(x => x is Folder) as Folder;
            Assert.AreEqual(folder.Name, openFolder.Name);
            Assert.AreEqual(folder.TargetFolderName, openFolder.TargetFolderName);
            Assert.AreEqual(folder.Items.Count, openFolder.Items.Count);

            Folder folder2 = folder.Items.First(x => x is Folder) as Folder;
            Folder openfolder2 = openFolder.Items.First(x => x is Folder) as Folder;
            Assert.AreEqual(folder2.Name, openfolder2.Name);
            Assert.AreEqual(folder2.TargetFolderName, openfolder2.TargetFolderName);
            Assert.AreEqual(folder2.Items.Count, openfolder2.Items.Count);

            ProjectItem item1 = folder.Items.First(x => x is ProjectItem) as ProjectItem;
            ProjectItem openItem1 = openFolder.Items.First(x => x is ProjectItem) as ProjectItem;
            Assert.AreEqual(item1.Name, openItem1.Name);
            Assert.AreEqual(item1.TargetFileName, openItem1.TargetFileName);
            Assert.AreEqual(item1.ReplaceParameters, openItem1.ReplaceParameters);

            ProjectItem item2 = document.TemplateContent.Items.First(x => x is ProjectItem) as ProjectItem;
            ProjectItem openItem2 = openedDocument.TemplateContent.Items.First(x => x is ProjectItem) as ProjectItem;
            Assert.AreEqual(item2.Name, openItem2.Name);
            Assert.AreEqual(item2.TargetFileName, openItem2.TargetFileName);
            Assert.AreEqual(item2.ReplaceParameters, openItem2.ReplaceParameters);

            //  Wizard Extension
            openedDocument = null;
            Assert.IsNull(document.WizardExtension);
            document.WizardExtension = new TemplateWizard();
            document.WizardExtension.Assembly = "SomeAssembly";
            document.WizardExtension.FullClassName = "SomeClass";

            documentType.Save(document, TestPath2);
            openedDocument = documentType.Open(TestPath2);

            Assert.IsNotNull(openedDocument.WizardExtension);
            Assert.AreEqual(document.WizardExtension.Assembly, openedDocument.WizardExtension.Assembly);
            Assert.AreEqual(document.WizardExtension.FullClassName, openedDocument.WizardExtension.FullClassName);
        }
    }
}
